<!--
 * @Author: lsjweiyi lsjweiyi
 * @Date: 2023-04-09 15:55:11
 * @LastEditors: lsjweiyi 759209794@qq.com
 * @LastEditTime: 2024-05-03 23:58:49
 * @FilePath: \web-ssg\pages\image\IdcardChangeColor.vue
 * @Description: 图像有损压缩
-->
<template>
    <div class="title">{{ toolIMsg.name }}</div>
    <div class="myBody">
        <div style="display: inline-flex;width: 80%;justify-content: center;align-items: center;">
            <span style="width:200px">期望图片大小(KB)：</span>
            <n-input-number v-model:value="needSize" clearable :precision="0" :min="0" :max="reginSize"
                placeholder="输入压缩后图片大小的期望值" />
        </div>
        <TwoImgCompare :bottom-img="upLoadImg" :bottom-label="'原图：' + reginSize + 'kb'" :upper-img="resultImg"
            :upper-label="resultLabel"></TwoImgCompare>
        <div class="buttonGroup">
            <div style="display: inline-flex;width: 100%;">
                <SingleFileUpload @select-file="fileChange" @upload-file="myUpload" :loading="loading"
                    :disabled="!isNeedSizeAccept"></SingleFileUpload>
            </div>
            <div style="display: inline-flex;width: 100%;"> <pay-and-down v-model:task-id="taskId"
                    :tool-name="toolIMsg.name" :tool-id="toolIMsg.toolId"></pay-and-down>
                <HistoryDown :tool-name="toolIMsg.name" :tool-id="toolIMsg.toolId"></HistoryDown>
            </div>
        </div>
        <div class="insideCard">
            <div style="color: red; margin-bottom: 10px">支持格式：jpg/jpeg、png</div>
            <div style="color: red; margin-bottom: 10px">{{ "限制大小：" + maxSize + "MB" }}</div>
            <div>{{ toolIMsg.description }}</div>
            <div style="font-size: 16px; margin-top: 10px">PS：本站不收集任何个人信息，请放心使用！上传的图片在服务器约保存24小时后自动删除</div>
        </div>
    </div>
</template>
<script lang="ts" setup>
import "@/assets/insideBody.scss";
import { createDiscreteApi } from "naive-ui";
const toolIMsg = getImageMenuItem("imgCompress");
const maxSize = 10; // 上传图片限制的大小，单位MB
useHead({
    title: toolIMsg.name,
});
useSeoMeta({
    description: toolIMsg.description,
});
const upLoadImg = ref<string | undefined>("/images/region1.jpg"); // 处理前的图片链接
const resultImg = ref<string | undefined>("/images/imgCompres2.jpg"); // 处理后的图片链接
const needSize = ref<number>(0); // 期望压缩到的大小
let taskId = ref("");
const reginSize = ref(52); // 压缩前图片大小
const resultLabel = ref("压缩后：20kb"); // 结果的label

const isNeedSizeAccept = ref(false); // needSize是否改变
const loading = ref(false);

let imgResultSize = 52; // 压缩后图片大小
// 自定义上传图像的方法覆盖默认方法
const myUpload = (file: File) => {
    loading.value = true; // 设置loading状态，防止重复点击上传按钮
    isNeedSizeAccept.value = false; // 每次上传后，则是一次新的判断阶段，所以需要重置
    isLimit = false; // 重置
    // 后端接口
    imgLossyCompress(file, needSize.value * 1024, toolIMsg.toolId as number).then((res) => {
        if (responseDeal(res, "图像有损压缩失败！", taskId, undefined, resultImg)) {
            imgResultSize = Math.round(Number(res.headers.get("Compress-Size")) / 1024);
            checkSizeLimit(imgResultSize, needSize.value);
            if (isLimit) {
                // 获取压缩有大小
                resultLabel.value = "压缩后：" + imgResultSize + "kb" + "(极限)";
            } else {
                // 获取压缩有大小
                resultLabel.value = "压缩后：" + imgResultSize + "kb";
            }
            lastNeddSize = needSize.value;
        }
        loading.value = false; // 设置loading状态，防止重复点击上传按钮
    });
};

/**
 * @description: 上传文件按钮回调函数
 * @param {*} file
 * @return {*}
 */
function fileChange(file: File, fn: (result: boolean) => void) {
    checkFile(file, maxSize * 1024, undefined, ["image/png", "image/jpeg"]).then((res) => {
        if (res) {
            upLoadImg.value = res.base64;
            resultImg.value = undefined;
            needSize.value = Math.round((file.size / 1024) * 0.8);
            reginSize.value = Math.round(file.size / 1024);
            fn(true);
            taskId.value = ""
        } else {
            fn(false);
        }
    });
}

let isLimit = false; // 是否压缩到极限
// 对比返回的图片大小，和期望值相比，如果返回的图片大小大于期望值，说明压缩到极限了，不允许继续压缩
function checkSizeLimit(imgSize: number, needSize: number) {
    if (imgSize > needSize) {
        const { message } = createDiscreteApi(["message"]);
        message.warning(`图片已压缩到极限！`, {
            duration: 5000,
        });
        isLimit = true;
    }
}

let lastNeddSize = 0; // 上次期望大小
// 监听期望大小变化，如果结果已经极限值，那么期望小于极限值，那么不允许上传处理。
// 如果结果值本就小于期望值，那么当继续减小期望值而还未小于结果值时，也不想允许上传处理
watch(needSize, () => {
    // 当前处于不能上传时才需要判断，因为如果已经换了图片，那肯定得允许
    // 如果结果已经是极限值，那么期望小于极限值，也无法获得更小的结果，那么不允许上传处理。
    if (isLimit && needSize.value <= imgResultSize) {
        isNeedSizeAccept.value = false;
        return;
    }
    // 如果结果值本就小于期望值，那么当继续减小期望值而还未小于结果值时，不允许上传处理
    if (needSize.value <= lastNeddSize && imgResultSize <= needSize.value) {
        isNeedSizeAccept.value = false;
        return;
    }
    isNeedSizeAccept.value = true;
});
</script>
<style  scoped>
.title::after {
    content: '图片有损压缩';
    position: absolute;
    left: 0;
    color: black;
    transform: translate(102px, 6px) scaleX(1.01) scaleY(0.5) skew(50deg);
    z-index: -1;
    filter: blur(1px);
    mask: linear-gradient(transparent, black);
}
</style>